package middleware

import (
	"errors"
	"net"
	"net/http"
	"os"
	"strings"

	"gitee.com/chewel/hermes/pkg/journal"
	"github.com/gin-gonic/gin"
)

type RecoveryBuilder struct {
	logger journal.ILogger
}

func NewRecoveryBuilder(logger journal.ILogger) *RecoveryBuilder {
	return &RecoveryBuilder{
		logger: logger,
	}
}

func (b *RecoveryBuilder) Build() gin.HandlerFunc {
	return func(c *gin.Context) {
		defer func() {
			if err := recover(); err != nil {
				var brokenPipe bool
				if ne, ok := err.(*net.OpError); ok {
					var se *os.SyscallError
					if errors.As(ne, &se) {
						seStr := strings.ToLower(se.Error())
						if strings.Contains(seStr, "broken pipe") ||
							strings.Contains(seStr, "connection reset by peer") {
							brokenPipe = true
						}
					}
				}
				if b.logger != nil {
					b.logger.Error("Application Panic And Recovery", journal.Error(err.(error)))
				}
				if brokenPipe {
					_ = c.Error(err.(error))
					c.Abort()
				} else {
					c.AbortWithStatus(http.StatusInternalServerError)
				}
			}
		}()
		c.Next()
	}
}
